package ep1;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class Dados implements Serializable{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	static List <Produto> BP = new ArrayList<Produto>();
	static List <Cliente> BC = new ArrayList<Cliente>();
	static List <Locacao> BL = new ArrayList<Locacao>();
	
	public static void loadData() 
	{
		openClientArchive();
		openProductArchive();
		openLocationArchive();
	}
	
	@SuppressWarnings("unchecked")
	private static void openClientArchive()
	{
		try {
			File arquivo; 
			arquivo = new File("Clientes.bin");
			if(! arquivo.exists())
			{ 
				ObjectOutputStream arqCliente1 = new ObjectOutputStream(new FileOutputStream(arquivo));
				arqCliente1.writeObject(BC);
				arqCliente1.close();	
			}
				FileInputStream arq= new FileInputStream(arquivo);
				ObjectInputStream arqCliente = new ObjectInputStream(arq);
				BC = (ArrayList<Cliente>) arqCliente.readObject();
				arqCliente.close();
			
			}
			catch(IOException e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
			} catch (ClassNotFoundException e) {
				System.out.println(e.getMessage());
				e.printStackTrace();
			}
	}
	
	@SuppressWarnings("unchecked")
	private static void openProductArchive()
	{
		try {
			File arquivo; 
			arquivo = new File("Produtos.bin");
			if(! arquivo.exists())
			{ 
				ObjectOutputStream arqProduto1 = new ObjectOutputStream(new FileOutputStream(arquivo));
				arqProduto1.writeObject(BP);
				arqProduto1.close();	
			}
			FileInputStream arq = new FileInputStream(arquivo);
			ObjectInputStream arqProduto= new ObjectInputStream(arq);
			BP = (ArrayList<Produto>) arqProduto.readObject();
			arqProduto.close();
			}
			catch(IOException e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
			} catch (ClassNotFoundException e) {
				System.out.println(e.getMessage());
				e.printStackTrace();
			}
	}
	
	@SuppressWarnings("unchecked")
	private static void openLocationArchive()
	{
		try {
			File arquivo; 
			arquivo = new File("Locacoes.bin");
			if(! arquivo.exists())
			{ 
				ObjectOutputStream arqLocacao1 = new ObjectOutputStream(new FileOutputStream(arquivo));
				arqLocacao1.writeObject(BL);
				arqLocacao1.close();	
			}
			FileInputStream arq = new FileInputStream(arquivo);
			ObjectInputStream arqLocacao= new ObjectInputStream(arq);
			BL = (ArrayList<Locacao>) arqLocacao.readObject();
			arqLocacao.close();
			}
			catch(IOException e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
			} catch (ClassNotFoundException e) {
				System.out.println(e.getMessage());
				e.printStackTrace();
			}
	}	
	//***********************************************************************
	
	private static boolean saveClients()
	{
		try
		{
			File arquivo;  
			   
			arquivo = new File("Clientes.bin"); 
			ObjectOutputStream arqCliente = new ObjectOutputStream(new FileOutputStream(arquivo));
			arqCliente.writeObject(BC);
			arqCliente.close();
			openClientArchive();
			return true;
		}
		catch(IOException e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
			return false;
		}
	}
	
	private static boolean saveProducts()
	{
		try
		{
			File arquivo;  
			   
			arquivo = new File("Produtos.bin"); 
			ObjectOutputStream arqProdutos = new ObjectOutputStream(new FileOutputStream(arquivo));
			arqProdutos.writeObject(BP);
			arqProdutos.close();
			openProductArchive();
			return true;
		}
		catch(IOException e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
			return false;
		}
	}
	
	private static boolean saveLocations()
	{
		try
		{
			File arquivo;  
			   
			arquivo = new File("Locacoes.bin"); 
			ObjectOutputStream arqLocacao = new ObjectOutputStream(new FileOutputStream(arquivo));
			arqLocacao.writeObject(BL);
			arqLocacao.close();
			openLocationArchive();
			return true;
		}
		catch(IOException e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
			return false;
		}
	}
	
	public static boolean addClient(Cliente CT) {
		if (findClientByRegisterNm(CT.getRegister())==null)
		{
			orderClientsByRegisterNm();
			BC.add(CT);
			if (saveClients())
				return true;
		} 
			return false;
	}

	//***********************************************************************
	
	public static boolean addProduct(Produto PT) {
		if (findProductByRegisterNm(PT.getRegister())==null)
		{
			orderProductsByRegisterNm();
			BP.add(PT);
			if (saveProducts())
				return true;
		}
			return false;
	}
	
	public static boolean addLocation(Locacao LC) {
			orderProductsByRegisterNm();
			BL.add(LC);
			if (saveLocations())
				return true;
			
			return false;
	}

	//***********************************************************************
	
	public static Cliente findClientByName(String name) {
		int i;
		for (i=0;i<BC.size();i++)
		{
			if (BC.get(i).getName().toUpperCase().compareToIgnoreCase(name.toUpperCase())>=0)
				return BC.get(i);
		}
		return null;
	}
	

	//***********************************************************************
	
	public static Cliente findClientByRegisterNm(int register) {
		int i;
		for (i=0;i<BC.size();i++)
		{
			if (BC.get(i).getRegister()==register)
				return BC.get(i);
		}
		
		return null;
	}

	//***********************************************************************
	
	public static Produto findProductByName(String name) {
		int i;
		for (i=0;i<BP.size();i++)
		{
			if (BP.get(i).getTitle().toUpperCase().compareToIgnoreCase(name.toUpperCase())>=0)
				return BP.get(i);
		}
		return null;
	}

	//***********************************************************************
	
	public static Produto findProductByRegisterNm(int register) {
		int i;
		for (i=0;i<BP.size();i++)
		{
			if (BP.get(i).getRegister()==register)
				return BP.get(i);
		}
		
		return null;
	}
	
	public static ArrayList<Locacao> findLocationByDateLocation(Date dateInitial, Date dateFinal) {
		int i;
		ArrayList<Locacao> arrayReturn = new ArrayList<Locacao>();
		for (i=0;i<BL.size();i++)
		{
			if (!BL.get(i).getData().after(dateInitial) && !BL.get(i).getData().before(dateInitial))
				arrayReturn.add(BL.get(i));
		}
		if (BL.size()!=0)
			return arrayReturn;
		
		return null;
	}
	
	public static ArrayList<Locacao> findLocationByDateDevolution(Date dateInitial, Date dateFinal) {
		int i;
		ArrayList<Locacao> arrayReturn = new ArrayList<Locacao>();
		for (i=0;i<BL.size();i++)
		{
			if (!BL.get(i).getDataDevolucao().after(dateInitial) && !BL.get(i).getDataDevolucao().before(dateInitial))
				arrayReturn.add(BL.get(i));
		}
		if (BL.size()!=0)
			return arrayReturn;
		
		return null;
	}
	
	public static ArrayList<Locacao> findLocationByClient(int register) {
		int i;
		ArrayList<Locacao> arrayReturn = new ArrayList<Locacao>();
		for (i=0;i<BL.size();i++)
		{
			if (BL.get(i).getClientRegister()==register)
				arrayReturn.add(BL.get(i));
		}
		if (BL.size()!=0)
			return arrayReturn;
		
		return null;
	}
	
	public static ArrayList<Locacao> findLocationByProduct(int register) {
		int i;
		ArrayList<Locacao> arrayReturn = new ArrayList<Locacao>();
		for (i=0;i<BL.size();i++)
		{
			for (int j=0;j<BL.get(i).getProductsRegister().size();j++)
			if (BL.get(i).getProductsRegister().get(j)==register)
			{
				arrayReturn.add(BL.get(i));
				break;
			}	
		}
		if (BL.size()!=0)
			return arrayReturn;
		
		return null;
	}

	//***********************************************************************
	
	public static void orderClientsByName() {
		for (int ivet = BC.size() - 1; ivet > 0; ivet--)
		{
			for (int isubv = 0; isubv < ivet; isubv++)
				if (BC.get(isubv).getName().compareToIgnoreCase(BC.get(isubv+1).getName())>0)
				{
					Cliente temp = BC.get(isubv);
					BC.set(isubv, BC.get(isubv+1));
					BC.set(isubv+1, temp);
				}
		}
		
	}

	//***********************************************************************
	
	public static void orderClientsByRegisterNm() {
		for (int ivet = BC.size() - 1; ivet > 0; ivet--)
		{
			for (int isubv = 0; isubv < ivet; isubv++)
				if (BC.get(isubv).getRegister() > BC.get(isubv+1).getRegister())
				{
					Cliente temp = BC.get(isubv);
					BC.set(isubv, BC.get(isubv+1));
					BC.set(isubv+1, temp);
				}
		}
		
	}

	
	public static void orderLocationsByDateLocation() {
		for (int ivet = BL.size() - 1; ivet > 0; ivet--)
		{
			for (int isubv = 0; isubv < ivet; isubv++)
				if (BL.get(isubv).getData().before(BL.get(isubv + 1).getData()))
				{
					Locacao temp = BL.get(isubv);
					BL.set(isubv, BL.get(isubv+1));
					BL.set(isubv+1, temp);
				}
		}
		
	}

	//***********************************************************************
	
	public static void orderProductsByName() {  
		for (int ivet = BP.size() - 1; ivet > 0; ivet--)
		{
			for (int isubv = 0; isubv < ivet; isubv++)
				if (BP.get(isubv).getTitle().compareToIgnoreCase(BP.get(isubv+1).getTitle())>0)
				{
					Produto temp = BP.get(isubv);
					BP.set(isubv, BP.get(isubv+1));
					BP.set(isubv+1, temp);
				}
		}
		
	}

	//***********************************************************************
	
	public static void orderProductsByRegisterNm() {
		for (int ivet = BP.size() - 1; ivet > 0; ivet--)
		{
			for (int isubv = 0; isubv < ivet; isubv++)
				if (BP.get(isubv).getRegister() > BP.get(isubv+1).getRegister())
				{
					Produto temp = BP.get(isubv);
					BP.set(isubv, BP.get(isubv+1));
					BP.set(isubv+1, temp);
				}
		}
		
	}

	//***********************************************************************
	
	public static void printClients() {
		orderClientsByName();
		genericPrint(BC);
		
	}
	
	public static void printClients(List<Cliente> BC) {
		orderClientsByName();
		genericPrint(BC);
		
	}

	//***********************************************************************
	
	public static void printProducts() {
		orderProductsByName();
		genericPrint(BP);
		
	}
	
	public static void printProducts(List<Produto> BP) {
		orderProductsByName();
		genericPrint(BP);
		
	}
	
	//***********************************************************************
	@SuppressWarnings("unchecked")
	private static <E> void genericPrint(List<E> arrayToPrint)
	{
		for(E element: arrayToPrint)
		{
			Class classOfObj = element.getClass();
			if(classOfObj.getName()=="ep1.Cliente")
			{
				Cliente xPrint = (Cliente) element;
				xPrint.printClientData();
				System.out.println("");
				
			}
			
			if(classOfObj.getName()=="ep1.Produto")
			{
				Produto xPrint = (Produto) element;
				xPrint.printProductData();
				System.out.println("");
			}
			
			if(classOfObj.getName()=="ep1.Locacao")
			{
				Locacao xPrint = (Locacao) element;
				xPrint.imprimeLocacao();
				System.out.println("");
			}
			
		}
	}

	//***********************************************************************
	
	public static boolean removeClient(Cliente CT) {
		if (findClientByRegisterNm(CT.getRegister())==null)
		{
			if (BC.remove(CT))
				if (saveClients())
					return true;
			else return false;
			
		}
			return false;
	}
	

	//***********************************************************************
	
	public static boolean removeProduct(Produto PT) {
		if (findProductByRegisterNm(PT.getRegister())==null)
		{
			if (BP.remove(PT))
				if (saveProducts())
					return true;
			else return false;
			
		}
			return false;
	}
	//***********************************************************************
	public static boolean changeClient(Cliente CT)
	{
		if (removeClient(CT))
			if (addClient(CT))
				return true;
		
		return false;
	}

	//***********************************************************************
	public static boolean changeProduct(Produto PT)
	{
		if (removeProduct(PT))
			if (addProduct(PT))
				return true;
		
		return false;
	}
	
}

